﻿using Application.Adapter;
using Application.Common.Extensions;
using Application.Common.Interface;
using Application.Plugins;
using Domain.Options;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Options;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using TouchSocket.Core;
using TouchSocket.Sockets;

namespace Infrastructure.Services
{

    /// <summary>
    /// 用于api和服务端的socket转发
    /// </summary>
    public class CustomTcpClient : ICustomTcpClient
    {
        public readonly TcpClient tcpClient = new TcpClient();
        public TcpClient TcpClient { get { return tcpClient; }}
        private readonly HeartbeatOptions HeartOption;
        public CustomTcpClient(IServiceProvider serviceProvider, IOptions<HeartbeatOptions> options)
        {
            HeartOption= options.Value;

            tcpClient.Connecting = (client, e) => {
                Console.WriteLine("11111");
            };//即将连接到服务器，此时已经创建socket，但是还未建立tcp
            tcpClient.Connected = (client, e) => {
                Console.WriteLine("2222");
            };//成功连接到服务器
            tcpClient.Disconnecting = (client, e) => {

                Console.WriteLine("333");
            };//即将从服务器断开连接。此处仅主动断开才有效。
            tcpClient.Disconnected = (client, e) => {
                Console.WriteLine("4444");
            };//从服务器断开连接，当连接不成功时不会触发。
            tcpClient.Received = (client, byteBlock, requestInfo) =>
            {
                if (requestInfo == null && byteBlock == null)
                {
                    tcpClient.Logger.Info($"客户端收到消息为null");
                    return;
                }

                if (byteBlock is not null)
                {
                    //从服务器收到信息。但是一般byteBlock和requestInfo会根据适配器呈现不同的值。
                    string mes = Encoding.UTF8.GetString(byteBlock.Buffer, 0, byteBlock.Len);
                    tcpClient.Logger.Info($"客户端CustomTcpClient Received 接收到信息：{mes}");
                }
                else
                {
                    if (requestInfo is BetweenAndRequestInfo myRequestInfo)
                    {
                        Console.WriteLine($"客户端CustomTcpClient Received 收到消息:{Convert.ToHexString(myRequestInfo.Body)}");

                        if (myRequestInfo.DataType == Domain.Enums.DataType.测试两个tcp)
                        {
                            Console.WriteLine("收到api命令21 ");
                            var data = "A5" + Convert.ToHexString(myRequestInfo.Body) + "5A";
                            client.Send(data.HexStringToByteArray());
                        }
                    }
                }

            };
            
            IPHost ipHost = default;
            ipHost = HeartOption.ListenPorts.Split(',')?.Select(c => int.Parse(c)).Select(p=>new IPHost(p)).First();
#if DEBUG
            ipHost = new IPHost("192.168.0.38:6638");
#endif
            //载入配置
            tcpClient.Setup(new TouchSocketConfig()
                .SetRemoteIPHost(ipHost)
                .SetTcpDataHandlingAdapter(() => new CustomBetweenAndDataHandlingAdapter())
                .ConfigurePlugins(a =>
                {
                    a.Add<CustomClientPlugin>();
                }));
        }

        public void Connect()
        {
            tcpClient.Connect();
        }

        public void Send(byte[] bytes)
        {
            tcpClient.Connect();
            tcpClient.Send(bytes);
            tcpClient.Close();
            tcpClient.Dispose();
        }
        public ResponsedData SendThenReceive(byte[] bytes,AdapterFilter adapterFilter=AdapterFilter.NoneAll)
        {

            tcpClient.Connect();
            var waitClient = tcpClient.GetWaitingClient(new WaitingOptions()
            {
                AdapterFilter = adapterFilter,
                BreakTrigger = true,//表示当连接断开时，会立即触发
                ThrowBreakException = true//表示当连接断开时，是否触发异常
            });

            //然后使用SendThenReturn。
            //byte[] returnData = waitClient.SendThenReturn(bytes,timeout:10000);
            //tcpClient.Logger.Info($"收到回应消息：{Encoding.UTF8.GetString(returnData)}");

            //同时，如果适配器收到数据后，返回的并不是字节，而是IRequestInfo对象时，可以使用SendThenResponse.
            ResponsedData responsedData = waitClient.SendThenResponse(bytes,timeout:10000);
            tcpClient.Close();
            tcpClient.Dispose();
            return responsedData;
        }
        public void TestOrderSend()
        {
            tcpClient.Connect();
            tcpClient.DefaultSend("测试在IBetweenAndRequestInfo 适配器下能否接受string参数，结果不能");
        }
    }
}
